package com.gitee.jktantan.datasource.monitor.analyze.metrics;

import com.codahale.metrics.Histogram;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Snapshot;
import com.codahale.metrics.Timer;
import com.codahale.metrics.health.HealthCheckRegistry;
import com.gitee.jktantan.datasource.monitor.analyze.entity.HistogramEntity;
import com.gitee.jktantan.datasource.monitor.analyze.entity.TimerEntity;
import com.gitee.jktantan.datasource.monitor.toolkit.HikariCPUtils;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;

/**
 * 数据源状态收集器
 */
@Component
public class MetricsCollector {

    private static final String WAIT = ".pool.Wait";
    private static final String USAGE = ".pool.Usage";
    private static final String CONNECTION_CREATION = ".pool.ConnectionCreation";
    //Meters
    private static final String CONNECTION_TIMEOUT_RATE = ".pool.ConnectionTimeoutRate";
    private static final String TOTAL_CONNECTIONS = ".pool.TotalConnections";
    private static final String IDLE_CONNECTIONS = ".pool.IdleConnections";
    private static final String ACTIVE_CONNECTIONS = ".pool.ActiveConnections";
    private static final String PENDING_CONNECTION = ".pool.PendingConnections";
    private static final String CONNECTIVITY_CHECK = ".pool.ConnectivityCheck";
    private static final String CONNECTION_99_PERCENT = ".pool.Connection99Percent";
    @Autowired(required = false)
    private MetricRegistry metricRegistry;
    @Autowired(required = false)
    private HealthCheckRegistry healthCheckRegistry;
    @Resource
    private List<DataSource> dataSources;
    @Resource
    private HikariCPUtils hikariCPUtils;
    //    private ConcurrentMap<String,StatisticsEntity> statisticsMap= new ConcurrentHashMap<>();

    public List<StatisticsEntity> getStatistics() {
        List<StatisticsEntity> statisticsEntities = new ArrayList<>();
        Snapshot snapshot;

        if (metricRegistry != null) {
            List<HikariDataSource> hikariDataSources = hikariCPUtils.getHikariDataSourceList(dataSources);
            for (HikariDataSource hikariDataSource : hikariDataSources) {
                StatisticsEntity statisticsEntity = new StatisticsEntity();
                statisticsEntity.setPoolName(hikariDataSource.getPoolName());
                try {
                    Connection connection = hikariDataSource.getConnection();
                    statisticsEntity.setUrl(connection.getMetaData().getURL());
                    connection.close();
                } catch (Exception e) {

                }
                TimerEntity wait = new TimerEntity();
                Timer timer = metricRegistry.getTimers().get(hikariDataSource.getPoolName() + WAIT);
                if (timer != null) {
                    wait.setCount(timer.getCount());
                    wait.setMeanRate(timer.getMeanRate());
                    wait.setM1Rate(timer.getOneMinuteRate());
                    wait.setM5Rate(timer.getFiveMinuteRate());
                    wait.setM15Rate(timer.getFifteenMinuteRate());
                    snapshot = timer.getSnapshot();

                    wait.setMin(snapshot.getMin());
                    wait.setMax(snapshot.getMax());
                    wait.setMean(snapshot.getMean());
                    wait.setStdDev(snapshot.getStdDev());
                    wait.setP50(snapshot.getMedian());
                    wait.setP75(snapshot.get75thPercentile());
                    wait.setP95(snapshot.get95thPercentile());
                    wait.setP98(snapshot.get98thPercentile());
                    wait.setP99(snapshot.get99thPercentile());
                    wait.setP999(snapshot.get999thPercentile());
                }
                statisticsEntity.setWait(wait);

                HistogramEntity usage = new HistogramEntity();
                Histogram histogram = metricRegistry.getHistograms().get(hikariDataSource.getPoolName() + USAGE);
                if (histogram != null) {
                    usage.setCount(histogram.getCount());

                    snapshot = histogram.getSnapshot();

                    usage.setMin(snapshot.getMin());
                    usage.setMax(snapshot.getMax());
                    usage.setMean(snapshot.getMean());
                    usage.setStdDev(snapshot.getStdDev());
                    usage.setP50(snapshot.getMedian());
                    usage.setP75(snapshot.get75thPercentile());
                    usage.setP95(snapshot.get95thPercentile());
                    usage.setP98(snapshot.get98thPercentile());
                    usage.setP99(snapshot.get99thPercentile());
                    usage.setP999(snapshot.get999thPercentile());

                }
                statisticsEntity.setUsage(usage);
                statisticsEntity.setTotalConnections(String.valueOf(metricRegistry.getGauges().get(hikariDataSource.getPoolName() + TOTAL_CONNECTIONS).getValue()));
                statisticsEntity.setIdleConnections(String.valueOf(metricRegistry.getGauges().get(hikariDataSource.getPoolName() + IDLE_CONNECTIONS).getValue()));
                statisticsEntity.setActiveConnections(String.valueOf(metricRegistry.getGauges().get(hikariDataSource.getPoolName() + ACTIVE_CONNECTIONS).getValue()));
                statisticsEntity.setPendingConnections(String.valueOf(metricRegistry.getGauges().get(hikariDataSource.getPoolName() + PENDING_CONNECTION).getValue()));
                try {
                    statisticsEntity.setConnectivityCheck(String.valueOf(healthCheckRegistry.runHealthCheck(hikariDataSource.getPoolName() + CONNECTIVITY_CHECK).isHealthy()));
                } catch (Exception e) {

                }
                statisticsEntities.add(statisticsEntity);
            }
        }
        return statisticsEntities;

    }
}
